package org.scboy.gateway.filters;

import java.util.HashMap;
import java.util.Map;

import org.scboy.gateway.cache.AuthPersmission;
import org.scboy.utils.entitys.rbac.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import cn.hutool.core.lang.UUID;
import reactor.core.publisher.Mono;

/**
 * 登录权限拦截
 * @author 杨浩
 */
@Configuration
public class AuthGlobalFilter implements GlobalFilter,Ordered {

	@Autowired
	AuthPersmission auth;
	
	@Override
	public int getOrder() {
		return Ordered.HIGHEST_PRECEDENCE-1;
	}

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		String path=exchange.getRequest().getPath().value();
		
		//获取转发的服务名称
		Route route =(Route) exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
	    String appName=route.getUri().toString().substring(5);
		/**
		 * 请求ID
		 */
		String requestId=UUID.randomUUID().toString();
		
		ServerHttpRequest mutableReq = exchange.getRequest().mutate()
                .header("Bmps-Request-Id", requestId)
                .build();
		
		//判断是否是动态服务地址
		if(path.startsWith("/dynamic/service")) {
			ServerHttpResponse response=exchange.getResponse();
			//返回登录过期
			byte[] data=new byte[0];
			try {
				Map<String, Object> result=new HashMap<String, Object>();
				result.put("status", 404);
				result.put("success", false);
				result.put("message", "请求地址找不到。");
				
				data = new ObjectMapper().writeValueAsBytes(result);
			} catch (JsonProcessingException e) {
				e.printStackTrace();
			}
			DataBuffer buffer=response.bufferFactory().wrap(data);
			return response.writeWith(Mono.just(buffer));
		}
		
		//判断是否是权限地址
		if(auth.checkAuthPath(appName,path) || path.startsWith("/dynamic/request")|| path.startsWith("/dynamic/test")) {

			//获取Token的Key
			String tokenKey=auth.getTokenKey();
			
			//获取Token
			String token=exchange.getRequest().getHeaders().getFirst(tokenKey);
			
			//检查登录状态,如果未登录
			LoginUser loginUser=auth.getLogin(token);
			if(loginUser==null) {
				ServerHttpResponse response=exchange.getResponse();
				//返回登录过期
				byte[] data=new byte[0];
				try {
					Map<String, Object> result=new HashMap<String, Object>();
					result.put("status", 401);
					result.put("success", false);
					result.put("message", "登录过期，请重新登录。");
					
					data = new ObjectMapper().writeValueAsBytes(result);
				} catch (JsonProcessingException e) {
					e.printStackTrace();
				}
				
				DataBuffer buffer=response.bufferFactory().wrap(data);
				return response.writeWith(Mono.just(buffer));
			}else {
				
				//判断是否开启了服务端地址请求权限认证
				if(auth.isServerAuthPath()) {
					
					//开启了后台权限认证，进行后台权限检查
					boolean check=auth.checkAuth(loginUser.getUserInfo().getId(), path);
					if(check) {
						return chain.filter(exchange.mutate().request(mutableReq).build());
					}else {
						ServerHttpResponse response=exchange.getResponse();
						
						//返回登录过期
						byte[] data=new byte[0];
						try {
							Map<String, Object> result=new HashMap<String, Object>();
							result.put("status", 407);
							result.put("success", false);
							result.put("message", "无访问权限请求，请联系系统管理员。");
							data = new ObjectMapper().writeValueAsBytes(result);
						} catch (JsonProcessingException e) {
							e.printStackTrace();
						}
						DataBuffer buffer=response.bufferFactory().wrap(data);
						return response.writeWith(Mono.just(buffer));
					}
				}else {
					return chain.filter(exchange.mutate().request(mutableReq).build());
				}
			}
		}
		
		return chain.filter(exchange.mutate().request(mutableReq).build());
	}

}
